<!DOCTYPE html>
<title>Test that CSSTransformComponent's toMatrix method is accurate.</title>
<script src="../resources/testharness.js"></script>
<script src="../resources/testharnessreport.js"></script>
<div id="translate-2d" style="transform: translate(20px, 10px)"></div>
<script>
  test(function() {
    // A 2D CSSTranslate should return a DOMMatrix in the form of:

    // 1 0 0 x
    // 0 1 0 y
    // 0 0 1 0
    // 0 0 0 1

    // where x is the pixel displacement in the x axis
    //   and y is the pixel displacement in the y axis.

    // In this case, we’re expecting this matrix to be equal to:
    // 1 0 0 20
    // 0 1 0 10
    // 0 0 1  0
    // 0 0 0  1

    const translate2D = document.getElementById("translate-2d")
        .computedStyleMap().get('transform')[0];
    assert_array_equals(translate2D.toMatrix().toFloat64Array(),
        [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 20, 10, 0, 1]);
  }, "2D CSSTranslate to DOMMatrix");
</script>
<div id="translate-3d" style="transform: translate3d(20px, 10px, 5px)"></div>
<script>
  test(function() {
    // A 3D CSSTranslate should return a DOMMatrix in the form of:

    // 1 0 0 x
    // 0 1 0 y
    // 0 0 1 z
    // 0 0 0 1

    // where x is the pixel displacement in the x axis,
    //       y is the pixel displacement in the y axis
    //   and z is the pixel displacement in the z axis.

    // In this case, we’re expecting this matrix to be equal to:
    // 1 0 0 20
    // 0 1 0 10
    // 0 0 1  5
    // 0 0 0  1

    const translate3D = document.getElementById("translate-3d")
        .computedStyleMap().get('transform')[0];
    assert_array_equals(translate3D.toMatrix().toFloat64Array(),
        [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 20, 10, 5, 1]);
  }, "3D CSSTranslate to DOMMatrix");
</script>
<div id="rotate-2d" style="transform: rotate(30deg)"></div>
<script>
  test(function() {
    // A 2D CSSRotate should return a DOMMatrix in the form of

    // cos(θ) -sin(θ) 0 0
    // sin(θ)  cos(θ) 0 0
    // 0       0      1 0
    // 0       0      0 1

    // where θ is the provided angle.

    // In this case, we’re expecting this matrix to be equal to:
    // √(3)/2 -0.5    0.0 0.0
    // 0.5     √(3)/2 0.0 0.0
    // 0.0     0.0    1.0 0.0
    // 0.0     0.0    0.0 1.0

    const rotate2D = document.getElementById("rotate-2d")
        .computedStyleMap().get('transform')[0];
    assert_array_approx_equals(rotate2D.toMatrix().toFloat64Array(),
        [Math.sqrt(0.75), 0.5, 0, 0, -0.5, Math.sqrt(0.75), 0, 0,
        0, 0, 1, 0, 0, 0, 0, 1], Number.EPSILON);
  }, "2D CSSRotate to DOMMatrix");
</script>
<div id="rotate-3d" style="transform: rotate3d(6, 3, 2, 30deg)"></div>
<script>
  test(function() {
    // A 3D CSSRotate should return a DOMMatrix in the form of

    // i² * (1 - cos(θ)) + 1 * cos(θ) | ij * (1 - cos(θ)) - k * sin(θ) | ik * (1 - cos(θ)) + j * sin(θ) | 0
    // ij * (1 - cos(θ)) + k * sin(θ) | j² * (1 - cos(θ)) + 1 * cos(θ) | jk * (1 - cos(θ)) - i * sin(θ) | 0
    // ik * (1 - cos(θ)) - j * sin(θ) | jk * (1 - cos(θ)) + i * sin(θ) | k² * (1 - cos(θ)) + 1 * cos(θ) | 0
    // 0                              | 0                              | 0                              | 1

    // where i is the normalized x component of the (x, y, z) vector,
    //       j is the normalized y component of the (x, y, z) vector,
    //       k is the normalized z component of the (x, y, z) vector,
    //       such as i² + j² + k² = 1 and i ÷ x = j ÷ y = k ÷ z
    //   and θ is provided angle.

    // In this case, we’re expecting this matrix to be equal to:

    // 36 / 49 + 13 * √(3) / 147 | 11 / 49 -  6 * √(3) /  49 |  45 / 98 -  4 * √(3) / 49 | 0
    // 25 / 49 -  6 * √(3) /  49 |  9 / 49 + 40 * √(3) / 147 | -15 / 49 -  2 * √(3) / 49 | 0
    //  3 / 98 -  4 * √(3) /  49 | 27 / 49 -  2 * √(3) /  49 |   4 / 49 + 15 * √(3) / 49 | 0
    //  0                        |  0                        |  0                        | 1

    const rotate3D = document.getElementById("rotate-3d")
        .computedStyleMap().get('transform')[0];
    assert_array_approx_equals(rotate3D.toMatrix().toFloat64Array(),
        [36 / 49 * (1 - Math.sqrt(0.75)) + Math.sqrt(0.75),
        18 / 49 * (1 - Math.sqrt(0.75)) + 1 / 7,
        12 / 49 * (1 - Math.sqrt(0.75)) - 3 / 14, 0,
        18 / 49 * (1 - Math.sqrt(0.75)) - 1 / 7,
        9 / 49 * (1 - Math.sqrt(0.75)) + Math.sqrt(0.75),
        6 / 49 * (1 - Math.sqrt(0.75)) + 3 / 7, 0,
        12 / 49 * (1 - Math.sqrt(0.75)) + 3 / 14,
        6 / 49 * (1 - Math.sqrt(0.75)) - 3 / 7,
        4 / 49 * (1 - Math.sqrt(0.75)) + Math.sqrt(0.75), 0, 0, 0, 0, 1],
        Number.EPSILON);
  }, "3D CSSRotate to DOMMatrix");
</script>
<div id="scale-2d" style="transform: scale(0.5, 1.5)"></div>
<script>
  test(function() {
    // A 2D CSSScale should return a DOMMatrix in the form of

    // x 0 0 0
    // 0 y 0 0
    // 0 0 1 0
    // 0 0 0 1

    // where x is the scaling with respect to the x axis
    //   and y is the scaling with respect to the y axis.

    // In this case, we’re expecting this matrix to be equal to:
    // 0.5 0.0 0.0 0.0
    // 0.0 1.5 0.0 0.0
    // 0.0 0.0 1.0 0.0
    // 0.0 0.0 0.0 1.0

    const scale2D = document.getElementById("scale-2d")
        .computedStyleMap().get('transform')[0];
    assert_array_equals(scale2D.toMatrix().toFloat64Array(),
        [0.5, 0, 0, 0, 0, 1.5, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]);
  }, "2D CSSScale to DOMMatrix");
</script>
<div id="scale-3d" style="transform: scale3d(0.5, 1.5, 2.5)"></div>
<script>
  test(function() {
    // A 3D CSSScale should return a DOMMatrix in the form of

    // x 0 0 0
    // 0 y 0 0
    // 0 0 z 0
    // 0 0 0 1

    // where x is the scaling with respect to the x axis,
    //       y is the scaling with respect to the y axis
    //   and z is the scaling with respect to the z axis.

    // In this case, we’re expecting this matrix to be equal to:
    // 0.5 0.0 0.0 0.0
    // 0.0 1.5 0.0 0.0
    // 0.0 0.0 2.5 0.0
    // 0.0 0.0 0.0 1.0

    const scale3D = document.getElementById("scale-3d")
        .computedStyleMap().get('transform')[0];
    assert_array_equals(scale3D.toMatrix().toFloat64Array(),
        [0.5, 0, 0, 0, 0, 1.5, 0, 0, 0, 0, 2.5, 0, 0, 0, 0, 1]);
  }, "3D CSSScale to DOMMatrix");
</script>
<div id="skew" style="transform: skew(45deg, 30deg);"></div>
<script>
  test(function() {
    // A CSSSkew should return a DOMMatrix in the form of

    // 1       tan(ax) 0 0
    // tan(ay) 1       0 0
    // 0       0       1 0
    // 0       0       0 1

    // where ax is the skewing angle along the x axis
    //   and ay is the skewing angle along the y axis.

    // In this case, we’re expecting this matrix to be equal to:
    // 1      1 0 0
    // √(3)/3 1 0 0
    // 0      0 1 0
    // 0      0 0 1

    const skew = document.getElementById("skew")
        .computedStyleMap().get('transform')[0];
    assert_array_approx_equals(skew.toMatrix().toFloat64Array(),
        [1, 3 ** -0.5, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1],
        Number.EPSILON);
  }, "CSSSkew to DOMMatrix");
</script>
<div id="skew-x" style="transform: skewX(45deg)"></div>
<script>
  test(function() {
    // A CSSSkewX should return a DOMMatrix in the form of

    // 1 tan(ax) 0 0
    // 0 1       0 0
    // 0 0       1 0
    // 0 0       0 1

    // where ax is the skewing angle along the x axis.

    // In this case, we’re expecting this matrix to be equal to:
    // 1 1 0 0
    // 0 1 0 0
    // 0 0 1 0
    // 0 0 0 1

    const skewX = document.getElementById("skew-x")
        .computedStyleMap().get('transform')[0];
    assert_array_approx_equals(skewX.toMatrix().toFloat64Array(),
        [1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], Number.EPSILON);
  }, "CSSSkewX to DOMMatrix");
</script>
<div id="skew-y" style="transform: skewY(30deg)"></div>
<script>
  test(function() {
    // A CSSSkewY should return a DOMMatrix in the form of

    // 1       0 0 0
    // tan(ay) 1 0 0
    // 0       0 1 0
    // 0       0 0 1

    // where ay is the skewing angle along the y axis.

    // In this case, we’re expecting this matrix to be equal to:
    // 1      0 0 0
    // √(3)/3 1 0 0
    // 0      0 1 0
    // 0      0 0 1

    const skewY = document.getElementById("skew-y")
        .computedStyleMap().get('transform')[0];
    assert_array_approx_equals(skewY.toMatrix().toFloat64Array(),
        [1, 3 ** -0.5, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1],
        Number.EPSILON);
  }, "CSSSkewY to DOMMatrix");
</script>
<div id="perspective" style="transform: perspective(50px)"></div>
<script>
  test(function() {
    // A CSSPerspective should return a DOMMatrix in the form of

    // 1 0 0        0
    // 0 1 0        0
    // 0 0 1        0
    // 0 0 (-1 / d) 1

    // where d is the length provided in pixels.

    // In this case, we’re expecting this matrix to be equal to:
    // 1.00 0.00  0.00 0.00
    // 0.00 1.00  0.00 0.00
    // 0.00 0.00  1.00 0.00
    // 0.00 0.00 -0.02 1.00

    const perspective = document.getElementById("perspective")
        .computedStyleMap().get('transform')[0];
    assert_array_equals(perspective.toMatrix().toFloat64Array(),
        [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, -0.02, 0, 0, 0, 1]);
  }, "CSSPerspective to DOMMatrix");
</script>
<div id="matrix-2d" style="transform: matrix(0, 1, -0.3, 1.5, 20, 10)"></div>
<script>
  test(function() {
    // A 2D CSSMatrixComponent should return a DOMMatrix in the form of

    // a c 0 e
    // b d 0 f
    // 0 0 1 0
    // 0 0 0 1

    // where a represent the a component of the matrix,
    //       b represent the b component of the matrix,
    //       c represent the c component of the matrix,
    //       d represent the d component of the matrix,
    //       e represent the e component of the matrix,
    //   and f represent the f component of the matrix.

    // In this case, we’re expecting this matrix to be equal to:
    // 0.0 -0.3 0.0 20.0
    // 1.0  1.5 0.0 10.0
    // 0.0  0.0 1.0  0.0
    // 0.0  0.0 0.0  1.0

    const matrix2D = document.getElementById("matrix-2d")
        .computedStyleMap().get('transform')[0];
    assert_array_equals(matrix2D.toMatrix().toFloat64Array(),
        [0, 1, 0, 0, -0.3, 1.5, 0, 0, 0, 0, 1, 0, 20, 10, 0, 1]);
  }, "2D CSSMatrixComponent to DOMMatrix");
</script>
<div id="matrix-3d" style="transform: matrix3d(0.5, 0.1, -0.1, 0,
    -0.1, 1.3, 0.7, 0, 0.6, -1.0, 2.2, 0, 20, 10, 5, 0.9)"></div>
<script>
  test(function() {
    // A 3D CSSMatrixComponent should return a DOMMatrix in the form of

    // m11 m21 m31 m41
    // m12 m22 m32 m42
    // m13 m23 m33 m43
    // m14 m24 m34 m44

    // where mij represent the element on the i-th column
    //                                 on the j-th row of the matrix.

    // In this case, we’re expecting this matrix to be equal to:
    //  0.5 -0.1  0.6 20.0
    //  0.1  1.3 -1.0 10.0
    // -0.1  0.7  2.2  5.0
    //  0.0  0.0  0.0  0.9

    const matrix3D = document.getElementById("matrix-3d")
        .computedStyleMap().get('transform')[0];
    assert_array_equals(matrix3D.toMatrix().toFloat64Array(), [0.5, 0.1, -0.1,
        0, -0.1, 1.3, 0.7, 0, 0.6, -1, 2.2, 0, 20, 10, 5, 0.9]);
  }, "3D CSSMatrixComponent to DOMMatrix");
</script>
